SurfaceFlinger之绘图缓冲区

SurfaceFlinger是GUI系统的核心服务,它主要负责图层的合成任务,同时它为每个应用程序维护一个Client,Client又是由多个Layer组成,Layer对应应用端的Window,这样SurfaceFlinger就能通过Layer来明白各个应用的绘图需求,从而将其合成显示。本篇将从SurfaceFlinger的角度来分析系统是如何通过Layer来管理绘图缓冲区。

缓冲队列

绘图缓冲区是通过BufferQueeu进行管理的,它是一个缓冲区队列,从生产消费的角度来说它同时为消费者和生产者,这里看看它的结构便可以知道

1
2
3
class BufferQueue : public BnGraphicBufferProducer,
public BnGraphicBufferConsumer,
private IBinder::DeathRecipient

BufferQueue同时是一个Binder,因此它也就具有跨进程的能力。本篇将会根据具体的使用来分析BufferQueue是如何同时作为消费者和生产者的。

BufferQueue的构成

BufferQueue内部是一个BufferSlot数组,大小为32,BufferSlot即Buffer槽用来描述一块缓冲区,需要注意的是BufferQueue在初始情况下并未分配缓冲区,只有当用户进行申请时才真正的分配缓冲区。一个缓冲区一旦被分配它便具有了状态,分别是:

FREE 表明该Buffer空闲,可以dequeue被生产者使用,此时它的拥有者为BufferQueue。

DEQUEUED 表示该Buffer已经被生产者dequeue,但还未入队或者取消,此时生产者是它的拥有者

QUEUED 表明这个Buffer已经被生产者填充好内容,等待消费者进行消费,此时它的拥有者为BufferQueue

ACQUIRED 表示该Buffer块被消费者获取到,此时消费者作为其拥有者。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
enum BufferState {
// FREE indicates that the buffer is available to be dequeued
// by the producer. The buffer may be in use by the consumer for
// a finite time, so the buffer must not be modified until the
// associated fence is signaled.
//
// The slot is "owned" by BufferQueue. It transitions to DEQUEUED
// when dequeueBuffer is called.
FREE = 0,

// DEQUEUED indicates that the buffer has been dequeued by the
// producer, but has not yet been queued or canceled. The
// producer may modify the buffer's contents as soon as the
// associated ready fence is signaled.
//
// The slot is "owned" by the producer. It can transition to
// QUEUED (via queueBuffer) or back to FREE (via cancelBuffer).
DEQUEUED = 1,

// QUEUED indicates that the buffer has been filled by the
// producer and queued for use by the consumer. The buffer
// contents may continue to be modified for a finite time, so
// the contents must not be accessed until the associated fence
// is signaled.
//
// The slot is "owned" by BufferQueue. It can transition to
// ACQUIRED (via acquireBuffer) or to FREE (if another buffer is
// queued in asynchronous mode).
QUEUED = 2,

// ACQUIRED indicates that the buffer has been acquired by the
// consumer. As with QUEUED, the contents must not be accessed
// by the consumer until the fence is signaled.
//
// The slot is "owned" by the consumer. It transitions to FREE
// when releaseBuffer is called.
ACQUIRED = 3
};

BufferQueue作为消费者

View在第一次进行绘制时会从WMS请求一个Surface绘图表面,这个绘图表面实际上会通过IGrpahicBufferProducer来请求绘图缓冲区,它实际上是一个IBinder Client,它的服务端即BufferQueue是在为WMS对应的Window对象创建SF端的Layer对象时创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void Layer::onFirstRef() {
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
mBufferQueue = new SurfaceTextureLayer(mFlinger);
mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mBufferQueue, mTextureName);
mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
mSurfaceFlingerConsumer->setFrameAvailableListener(this);
mSurfaceFlingerConsumer->setName(mName);

#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
#warning "disabling triple buffering"
mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
#else
mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);
#endif

const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
updateTransformHint(hw);
}

这里的SurfaceTextureLayer是BufferQueue的子类,它在Layer对象被创建后第一次引用时创建。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
{
// initialize the surfaces
switch (format) {
case PIXEL_FORMAT_TRANSPARENT:
case PIXEL_FORMAT_TRANSLUCENT:
format = PIXEL_FORMAT_RGBA_8888;
break;
case PIXEL_FORMAT_OPAQUE:
#ifdef NO_RGBX_8888
format = PIXEL_FORMAT_RGB_565;
#else
format = PIXEL_FORMAT_RGBX_8888;
#endif
break;
}

#ifdef NO_RGBX_8888
if (format == PIXEL_FORMAT_RGBX_8888)
format = PIXEL_FORMAT_RGBA_8888;
#endif

*outLayer = new Layer(this, client, name, w, h, flags);
status_t err = (*outLayer)->setBuffers(w, h, format, flags);
if (err == NO_ERROR) {
*handle = (*outLayer)->getHandle();
*gbp = (*outLayer)->getBufferQueue();
}

return err;
}

可以看到Layer被创建后,通过getBufferQueue得到该缓冲队列,这个队列是以一个Binder代理返回给应用端的,应用端最终是通过该BufferQueue来请求缓冲区,从而通过该缓冲区构造SkCanvas最终提交给上层使用的。从这个角度来讲BufferQueue是作为生产者的。

坚持原创技术分享,您的支持将鼓励我继续创作!